#include "../../platform/ixus970_sd890/leds.h"

static void __attribute__((noreturn)) shutdown();
static void __attribute__((noreturn)) panic(int cnt);

extern long *blob_chdk_core;
extern long *blob_copy_and_reset;
extern long blob_chdk_core_size;
extern long blob_copy_and_reset_size;

void __attribute__((noreturn)) my_restart()
{
	void __attribute__((noreturn)) (*copy_and_restart)(char *dst, char *src, long length);
	int i;

	for (i=0; i<(blob_copy_and_reset_size/sizeof(long)); i++) {
		((long*)(RESTARTSTART))[i] = blob_copy_and_reset[i];
	}

	copy_and_restart = (void*)RESTARTSTART;
	copy_and_restart((void*)MEMISOSTART, (char*)blob_chdk_core, blob_chdk_core_size);
}

static void __attribute__((noreturn)) shutdown()
{
	// @ FF829C28
	volatile long *p = (void*)0xC022001C;

	asm (
		"MRS     R1, CPSR\n"
		"AND     R0, R1, #0x80\n"
		"ORR     R1, R1, #0x80\n"
		"MSR     CPSR_cf, R1\n"
		:::"r1","r0");

	*p = 0x44; // led off

	while(1);
}

static void __attribute__((noreturn)) panic(int cnt)
{
	volatile long *p=(void*)LED_PR;
	int i;

	for(;cnt>0;cnt--) {
		p[0]=0x46;

		for(i=0;i<0x200000;i++) {
			asm ("nop\n");
			asm ("nop\n");
		}
		p[0]=0x44;
		for(i=0;i<0x200000;i++) {
			asm ("nop\n");
			asm ("nop\n");
		}
	}
	shutdown();
}
